﻿using System;
using System.Collections.Generic;
using System.Management;

namespace Model.Nova
{
    public class MachineLookupTable
    {
        private readonly Dictionary<String, LookupMachine> lookupTable;
        private readonly Dictionary<LookupMachine, String> reverseLookupTable;
        private readonly Dictionary<String, LookupMachine> identityLookupTable;
        /// <summary>
        /// Gets the total number of machines registered in the lookup table.
        /// </summary>
        public long Count
        {
            get { return lookupTable.Count; }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="MachineLookupTable"/> class.
        /// </summary>
        public MachineLookupTable()
        {
            lookupTable = new Dictionary<string, LookupMachine>(10000);
            identityLookupTable = new Dictionary<string, LookupMachine>(10000);
            reverseLookupTable = new Dictionary<LookupMachine, string>(10000);
        }

        /// <summary>
        /// Purges all Machines from the database and releases all active IDs.
        /// </summary>
        public void Reset()
        {
            lookupTable.Clear();
            reverseLookupTable.Clear();

            identityLookupTable.Clear();
        }

        public enum Status
        {
            Successed,
            RegistedByOtherMachine,
            Failed,
        }
        /// <summary>
        /// 注册无人值守账户
        /// </summary>
        /// <param name="machineSever"></param>
        /// <returns></returns>
        public Status RegisterNoManMachine(Machine machineSever)
        {
            string strName = machineSever.NovaId;
            string strPasswordHash = machineSever.PasswordHash;
            string strIdentity = machineSever.Identity;
            if (MachineDbHelper.Instance.NameExist(strName,strIdentity))
            {
                return  Status.RegistedByOtherMachine;
            }
            int  ret = MachineDbHelper.Instance.SaveDbMachine(strName,strPasswordHash,strIdentity);


            return ret>0 ? Status.Successed : Status.Failed;
        }

        public LookupMachine GetMachineWithDb(Machine machineInfo)
        {
            var ret = GetMachineById(machineInfo.NovaId);
            if (ret != null) return ret;

            var dbMachine = MachineDbHelper.Instance.GetDbMachine(machineInfo.NovaId);
            if (dbMachine == null) return null;

            var copySrc = GetMachineByidentity(dbMachine.Identity);
            if (copySrc == null) return null;

            dbMachine.PrivateEndPoint = copySrc.Machine.PrivateEndPoint;
            dbMachine.PublicEndPoint = copySrc.Machine.PublicEndPoint;
            ret = new LookupMachine(dbMachine);

            return ret;
        }

        /// <summary>
        /// 通过中介分配的ID进行索引
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public LookupMachine GetMachineById(string key)
        {
            try
            {
                return lookupTable[key];
            }
            catch (KeyNotFoundException )
            {
                return null;
            }
        }
        /// <summary>
        /// 通过硬盘码获取机器对象
        /// </summary>
        /// <param name="key">每台机器的硬盘码是不变的</param>
        /// <returns></returns>
        public LookupMachine GetMachineByidentity(string key)
        {
            try
            {
                return identityLookupTable[key];
            }
            catch (KeyNotFoundException )
            {
                return null;
            }
        }
        public string GetIdByMachine(LookupMachine machine)
        {
            return reverseLookupTable[machine];
        }

        /// <summary>
        /// Returns true if the the ID, exists.
        /// </summary>
        public bool IdExists(string id)
        {
            return (lookupTable.ContainsKey(id));
        }
        /// <summary>
        /// Returns true if the the identity, exists.
        /// </summary>
        public bool IdentityExists(string id)
        {
            return (identityLookupTable.ContainsKey(id));
        }
        /// <summary>
        /// Returns true if the the identity, exists.
        /// </summary>
        public bool IdentityExists(LookupMachine machine)
        {
            return (identityLookupTable.ContainsKey(machine.Machine.Identity));
        }
        /// <summary>
        /// Returns true if the the ID, exists.
        /// </summary>
        public bool IdExists(LookupMachine machine)
        {
            return (reverseLookupTable.ContainsKey(machine));
        }

        public void Add(string id, LookupMachine machine)
        {
            if (!IdExists(id))
            {
                lookupTable.Add(id, machine);
                reverseLookupTable.Add(machine, id);
                identityLookupTable.Add(machine.Machine.Identity, machine);

            }
            else
            {
                lookupTable[id] = machine;
                reverseLookupTable[machine] = id;
                identityLookupTable[machine.Machine.Identity] = machine;
            }
        }

        public void Add(LookupMachine machine, string id)
        {
            if (!IdExists(machine))
            {
                reverseLookupTable.Add(machine, id);
                lookupTable.Add(id, machine);
                identityLookupTable.Add(machine.Machine.Identity, machine);
            }
            else
            {
                reverseLookupTable[machine] = id;
                lookupTable[id] = machine;
                identityLookupTable[machine.Machine.Identity] = machine;

            }
        }

        public void Remove(string id)
        {
            if (IdExists(id))
            {
                reverseLookupTable.Remove(GetMachineById(id));
                lookupTable.Remove(id);
                identityLookupTable.Remove(GetMachineById(id).Machine.Identity);
            }
        }

        //public LookupMachine GetMachineByComputeIdentity;
        public void Remove(LookupMachine machine)
        {
            if (IdExists(machine))
            {
                lookupTable.Remove(GetIdByMachine(machine));
                reverseLookupTable.Remove(machine);
                identityLookupTable.Remove(machine.Machine.Identity);
            }
        }
    }
}